package com.zjuee.base.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @author wu liang
 * @since 1.0
 */
public final class AESUtils {

    private static Logger logger = LoggerFactory.getLogger(AESUtils.class);
    private final static String AES_OPTIONS = "AES/CBC/PKCS5Padding";
    private final static String AES_NAME = "AES";
    private static final Base64.Encoder encoder = Base64.getEncoder();
    public final static String KEY = "226f8e2c0bbb812b";
    public final static String IV = "1234567812345678";

    public static String encode(Cipher encodeCipher, String text) {
        if (StringUtils.isEmpty(text) || null == encodeCipher) {
            return null;
        }

        try {
            return new String(Base64.getEncoder().encode(encodeCipher.doFinal(text.getBytes(StandardCharsets.UTF_8))),
                    StandardCharsets.UTF_8);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    public static String decode(Cipher decodeCipher, String text) {
        if (StringUtils.isEmpty(text) || null == decodeCipher) {
            return null;
        }

        try {
            return new String(decodeCipher.doFinal(Base64Utils.decode(text)), StandardCharsets.UTF_8);
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    public static Cipher createEncoder(String aesKey, String aesIV) {
        if (StringUtils.isEmpty(aesKey) || StringUtils.isEmpty(aesIV)) {
            throw new NullPointerException(" input key or iv is null");
        }

        try {
            Cipher encodeCipher = Cipher.getInstance(AES_OPTIONS);
            encodeCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), AES_NAME),
                    new IvParameterSpec(aesIV.getBytes(StandardCharsets.UTF_8)));

            return encodeCipher;
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    public static Cipher createDecoder(String aesKey, String aesIV) {
        if (StringUtils.isEmpty(aesKey) || StringUtils.isEmpty(aesIV)) {
            throw new NullPointerException(" input key or iv is null");
        }

        try {
            Cipher decodeCipher = Cipher.getInstance(AES_OPTIONS);
            decodeCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), AES_NAME),
                    new IvParameterSpec(aesIV.getBytes(StandardCharsets.UTF_8)));

            return decodeCipher;
        } catch (Exception e) {
            logger.error("", e);
        }
        return null;
    }

    public static String encode(String aesKey, String aesIV, String content) {
        return encode(createEncoder(StringUtils.isBlank(aesKey) ? KEY : aesKey, StringUtils.isBlank(aesIV) ? IV : aesIV), content);
    }

    public static String decode(String aesKey, String aesIV, String content) {
        return decode(createDecoder(StringUtils.isBlank(aesKey) ? KEY : aesKey, StringUtils.isBlank(aesIV) ? IV : aesIV), content);
    }


    public static String encrypt(String encData, String key) throws Exception {
        String data = encData;
        String iv = "1234567812345678";
        //根据指定算法AES自成密码器
        Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding", "BC");
        byte[] dataBytes = data.getBytes("UTF-8");
        SecretKeySpec keyspec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
        IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes("UTF-8"));
        //初始化密码器，第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作，第二个参数为使用的KEY
        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
        //根据密码器的初始化方式--加密：将数据加密
        byte[] encrypted = cipher.doFinal(dataBytes);
        return encoder.encodeToString(encrypted);
    }
}
